/*
Copyright (c) 2010 Andreas Bjerkeholt
License: MIT
http://www.opensource.org/licenses/mit-license.php
*/
#ifdef SML
#include "graphics_sml.h"
#include "images.h"

extern char* errorMsg;

display* gameDisplay  = NULL;

gfx_font* gameFont       = NULL;
gfx_font* gameFontYellow = NULL;
gfx_font* gameFontGrey   = NULL;
gfx_font* gameFontBlack  = NULL;

sprite* gameTiles;

gfx_texture* gameSplash         = NULL;
gfx_texture* menuBg             = NULL;
sprite* hudSmallKeyRed          = NULL;
sprite* hudSmallKeyBlue         = NULL;
sprite* hudSmallKeyGreen        = NULL;
sprite* hudSmallKeyYellow       = NULL;
sprite* hudFireBootsSmall       = NULL;
sprite* hudFlippersSmall        = NULL;
sprite* hudSkatesSmall          = NULL;
sprite* hudSuctionBootsSmall    = NULL;
sprite* checkmark               = NULL;
sprite* yellowArrow             = NULL;

inline uint32_t gfx_color_back(gfx_color inColor) {
		return ((inColor & 0xF800) << 8) | ((inColor & 0x07E0) << 5) | ((inColor & 0x001F) << 3);
}

bool initGfx()
{
	gameDisplay = display_create(320, 240, 320, (DISPLAY_FORMAT_RGB565 | DISPLAY_BUFFER_STATIC), NULL, NULL);
	if(gameDisplay == NULL)
	{
		return false;
	}
	gfx_init(gameDisplay);

	return true;
}

void termGfx()
{
	gfx_term();
	display_delete(gameDisplay);
}

void drawText(int x, int y, gfx_font* font, char* text)
{
	gfx_font_print(x, y, font, text);
}

void drawChar(int x, int y, gfx_font* font, char c)
{
	gfx_font_print_char(x, y, font, c);
}

void drawTextCenter(int y, gfx_font* font, char* text)
{
	gfx_font_print_center(y, font, text);
}

void drawTexture(int x, int y, gfx_texture* tex)
{
	gfx_tex_draw(x, y, tex);
}

void drawSprite(int x, int y, sprite* sprite)
{
	sprite_draw(sprite, x, y, 0);
}

void drawTileGfx(int x, int y, uint8_t tileNo)
{
	sprite_draw(gameTiles, x, y, tileNo);
}

void drawRect(int x, int y, int w, int h, gfx_color color)
{
	gfx_rect_draw(x, y, w, h, color);
}

void drawRectFill(int x, int y, int w, int h, gfx_color color)
{
	gfx_rect_fill_draw(x, y, w, h, color);
}

void drawLine(int x1, int y1, int x2, int y2, gfx_color color)
{
	gfx_line_draw(x1, y1, x2, y2, color);
}

void clearScreen(gfx_color inColor)
{
	gfx_render_target_clear(inColor);
}

void flipDisplay()
{
	display_flip(gameDisplay);
}

void fadeScreen(int8_t percent)
{
	if (percent >= 100)
		return;
	if (percent < 0)
		percent = 0;

	uint16_t* tempTexPtr = gfx_render_target->address;
	uint32_t i;
	uint32_t totpx;
	uint16_t red;
	uint16_t green;
	uint16_t blue;

	totpx = gfx_render_target->width * gfx_render_target->height;
	for (i = 0; i < totpx; i++)
	{
		if (tempTexPtr[i] == 0)
			continue;

		red = (tempTexPtr[i] & 0xF800);
		green = (tempTexPtr[i] & 0x07E0);
		blue = (tempTexPtr[i] & 0x001F);

		red = (red * percent) / 100;
		green = (green * percent) / 100;
		blue = (blue * percent) / 100;

		red = red & 0xF800;
		green = green & 0x07E0;
		blue = blue & 0x001F;
		
		tempTexPtr[i] = (red | green | blue);
	}
}

bool loadFirstGfx() // Splash and base font
{
	gameFont = gfx_font_load_from_buffer(gfxFont, gfxFontSize, COLOR_MAGENTA);
	gameSplash = gfx_tex_load_tga_from_buffer(gfxSplash, gfxSplashSize);

	if (gameFont == NULL || gameSplash == NULL)
	{
		gfx_font_delete(gameFont);
		gfx_tex_delete(gameSplash);
		return false;
	}

	return true;
}

sprite* loadTileset()
{
	gfx_texture* fullTileset = NULL;
	gfx_texture* tempTile = NULL;
	sprite* outSprite = NULL;
	
	fullTileset = gfx_tex_load_tga_from_buffer(gfxTiles, gfxTilesSize);
	tempTile = gfx_tex_allocate(TILESIZE, TILESIZE);
	outSprite = sprite_create(TILESIZE, TILESIZE);

	if (fullTileset == NULL || tempTile == NULL || outSprite == NULL)
	{
		gfx_tex_delete(fullTileset);
		gfx_tex_delete(tempTile);
		sprite_delete(outSprite);
		return NULL;
	}

	uint16_t* tempSource = fullTileset->address;
	uint16_t* tempTarget = tempTile->address;

	int tileX, tileY, x, y, srcX, srcY;
	for (tileX = 0; tileX < 7; tileX++)
	{
		for (tileY = 0; tileY < 16; tileY++)
		{
			// Copy tile to temporary texture
			for (y = 0; y < TILESIZE; y++)
			{
				srcY = tileY * TILESIZE + y;

				for (x = 0; x < TILESIZE; x++)
				{
					srcX = tileX * TILESIZE + x;

					tempTarget[(y * TILESIZE) + x] = tempSource[(srcY * fullTileset->width) + srcX];
				}
			}

			// Build sprite frame from temporary texture
			outSprite = sprite_frame_add_bitmap(outSprite, tempTarget, COLOR_MAGENTA);
			if (outSprite == NULL)
			{
				gfx_tex_delete(fullTileset);
				gfx_tex_delete(tempTile);
				return NULL;
			}
		}
	}

	gfx_tex_delete(fullTileset);
	gfx_tex_delete(tempTile);
	return outSprite;
}

bool loadGfx()
{
	gameTiles = loadTileset();

	hudSmallKeyBlue = sprite_load_from_tga_buffer(gfxHudKeyBlue, gfxHudKeyBlueSize, COLOR_MAGENTA);
	hudSmallKeyRed = sprite_load_from_tga_buffer(gfxHudKeyRed, gfxHudKeyRedSize, COLOR_MAGENTA);
	hudSmallKeyGreen = sprite_load_from_tga_buffer(gfxHudKeyGreen, gfxHudKeyGreenSize, COLOR_MAGENTA);
	hudSmallKeyYellow = sprite_load_from_tga_buffer(gfxHudKeyYellow, gfxHudKeyYellowSize, COLOR_MAGENTA);

	hudFlippersSmall = sprite_load_from_tga_buffer(gfxHudFlippers, gfxHudFlippersSize, COLOR_MAGENTA);
	hudFireBootsSmall = sprite_load_from_tga_buffer(gfxHudFireBoots, gfxHudFireBootsSize, COLOR_MAGENTA);
	hudSkatesSmall = sprite_load_from_tga_buffer(gfxHudSkates, gfxHudSkatesSize, COLOR_MAGENTA);
	hudSuctionBootsSmall = sprite_load_from_tga_buffer(gfxHudSuctionBoots, gfxHudSuctionBootsSize, COLOR_MAGENTA);

	checkmark = sprite_load_from_tga_buffer(gfxCheckmark, gfxCheckmarkSize, COLOR_MAGENTA);
	yellowArrow = sprite_load_from_tga_buffer(gfxYellowArrow, gfxYellowArrowSize, COLOR_MAGENTA);
	menuBg = gfx_tex_load_tga_from_buffer(gfxMenuBg, gfxMenuBgSize);

	// gameFont and gameSplash are loaded in loadFirstGfx(), so we can draw them (hopefully), even if something else fails here.

	// ERROR CHECK (NULL POINTERS)

	if (gameTiles == NULL)
	{
		errorMsg = "Unable to load graphics (1)";
		return false;
	}

	if (hudSmallKeyBlue == NULL || hudSmallKeyRed == NULL || hudSmallKeyGreen == NULL ||
		hudSmallKeyYellow == NULL || hudFlippersSmall == NULL || hudFireBootsSmall == NULL ||
		hudSkatesSmall == NULL || hudSuctionBootsSmall == NULL || gameFont == NULL || gameSplash == NULL ||
		checkmark == NULL || menuBg == NULL || yellowArrow == NULL)
	{
		errorMsg = "Unable to load graphics (2)";
		return false;
	}

	gameFontYellow = malloc(sizeof(gfx_font));
	gameFontGrey = malloc(sizeof(gfx_font));
	gameFontBlack = malloc(sizeof(gfx_font));

	if (gameFontYellow == NULL || gameFontGrey == NULL || gameFontBlack == NULL)
	{
		errorMsg = "Unable to load graphics (3)";
		return false;
	}

	gameFontYellow->texture = gfx_tex_allocate(gameFont->texture->width, gameFont->texture->height);
	gameFontGrey->texture = gfx_tex_allocate(gameFont->texture->width, gameFont->texture->height);
	gameFontBlack->texture = gfx_tex_allocate(gameFont->texture->width, gameFont->texture->height);

	if (gameFontYellow->texture == NULL || gameFontGrey->texture == NULL || gameFontBlack->texture == NULL)
	{
		errorMsg = "Unable to load graphics (4)";
		return false;
	}

	gameFontYellow->colorKey = COLOR_MAGENTA;
	gameFontGrey->colorKey = COLOR_MAGENTA;
	gameFontBlack->colorKey = COLOR_MAGENTA;
	gameFontYellow->colorize = false;
	gameFontGrey->colorize = false;
	gameFontBlack->colorize = false;

	uint16_t* tempSrcTexPtr = gameFont->texture->address;
	uint16_t* tempTrgTexPtrYellow = gameFontYellow->texture->address;
	uint16_t* tempTrgTexPtrGrey = gameFontGrey->texture->address;
	uint16_t* tempTrgTexPtrBlack = gameFontBlack->texture->address;
	uintptr_t ptr;
	for (ptr = 0; ptr < (gameFont->texture->width * gameFont->texture->height); ptr++)
	{
		if (tempSrcTexPtr[ptr] == COLOR_MAGENTA)
		{
			// Preserve transparency
			tempTrgTexPtrYellow[ptr] = tempSrcTexPtr[ptr];
			tempTrgTexPtrGrey[ptr] = tempSrcTexPtr[ptr];
			tempTrgTexPtrBlack[ptr] = tempSrcTexPtr[ptr];
		}
		else
		{
			uint32_t color = gfx_color_back(tempSrcTexPtr[ptr]);
			uint8_t tempRed = (uint8_t)(color >> 16);
			uint8_t tempGreen = (uint8_t)(color >> 8);
			uint8_t tempBlue = (uint8_t)color;

			tempTrgTexPtrYellow[ptr] = gfx_color_rgb(tempRed, tempGreen, 0x00);
			tempTrgTexPtrGrey[ptr] = gfx_color_rgb(
				tempRed >= 0x6F ? tempRed - 0x6F : 0x00,
				tempGreen >= 0x6F ? tempGreen - 0x6F : 0x00,
				tempBlue >= 0x6F ? tempBlue - 0x6F : 0x00);
			tempTrgTexPtrBlack[ptr] = COLOR_BLACK;
		}
	}

	return true;
}

void unloadGfx()
{
	sprite_delete(gameTiles);
	gfx_font_delete(gameFont);
	gfx_font_delete(gameFontYellow);
	gfx_font_delete(gameFontGrey);
	gfx_font_delete(gameFontBlack);
	gfx_tex_delete(gameSplash);
	gfx_tex_delete(menuBg);
	sprite_delete(hudFireBootsSmall);
	sprite_delete(hudFlippersSmall);
	sprite_delete(hudSkatesSmall);
	sprite_delete(hudSuctionBootsSmall);
	sprite_delete(hudSmallKeyRed);
	sprite_delete(hudSmallKeyBlue);
	sprite_delete(hudSmallKeyGreen);
	sprite_delete(hudSmallKeyYellow);
	sprite_delete(checkmark);
	sprite_delete(yellowArrow);
}

/*void gfxSaveTga
	gfx_tex_save_tga(filename, gfx_render_target);*/

#endif
